/*
 * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
 * The software in this package is published under the terms of the CPAL v1.0
 * license, a copy of which has been included with this distribution in the
 * LICENSE.txt file.
 */

package org.mule.extension.db.internal.domain.type;

import static java.sql.Types.STRUCT;
import static org.hamcrest.Matchers.arrayContaining;
import static org.hamcrest.Matchers.equalTo;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.hamcrest.MockitoHamcrest.argThat;
import org.mule.extension.db.internal.domain.connection.DbConnection;
import org.mule.tck.junit4.AbstractMuleTestCase;
import org.mule.tck.size.SmallTest;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.Struct;
import java.util.ArrayList;
import java.util.List;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

@SmallTest
public class StructDbTypeTestCase extends AbstractMuleTestCase {

  private static final int PARAM_INDEX = 1;
  private static final String TYPE_NAME = "testStruct";

  @Rule
  public ExpectedException expectedException = ExpectedException.none();

  private StructDbType dataType;
  private PreparedStatement statement;
  private Connection connection;
  private DbConnection dbConnection;
  private Struct struct;

  @Before
  public void setUp() throws Exception {
    dataType = new StructDbType(STRUCT, TYPE_NAME);
    statement = mock(PreparedStatement.class);
    connection = mock(Connection.class);
    dbConnection = mock(DbConnection.class);
    struct = mock(Struct.class);

    when(statement.getConnection()).thenReturn(connection);
  }

  @Test
  public void convertsArrayToStruct() throws Exception {
    Object[] value = new Object[] {"foo", "bar"};

    when(connection.createStruct(TYPE_NAME, value)).thenReturn(struct);

    dataType.setParameterValue(statement, PARAM_INDEX, value, dbConnection);

    verify(statement).setObject(PARAM_INDEX, struct, STRUCT);
  }

  @Test
  public void convertsListToStruct() throws Exception {
    List<String> value = new ArrayList<>();
    value.add("foo");
    value.add("bar");
    when(connection.createStruct(argThat(equalTo(TYPE_NAME)), argThat(arrayContaining("foo", "bar")))).thenReturn(struct);

    dataType.setParameterValue(statement, PARAM_INDEX, value, dbConnection);

    verify(statement).setObject(PARAM_INDEX, struct, STRUCT);
  }
}
